import { ref, watch } from 'vue';
import { isArray, isObject } from '@/utils/is';

/** @typedef {import('../utils/type.js').I18nOptions} I18nOptions */

/**
 * 默认处理国际化的方法，直接返回tokens
 * @param {string} tokens 获取对应国际化字符串的令牌
 * @returns {string}
 */
const noop = (tokens) => tokens;

/**
 * 替换字符串中的占位符
 * @param {string} rawString 原始字符串
 * @param {Object | Array | string} replacer 替换的内容
 * @returns {string} 处理后的字符串
 */
const replace = (rawString, replacer) => {
	if (replacer) {
		// replacer是对象或数组
		// 则根据replacer的key替换
		// 否则直接根据${0}替换
		if (isObject(replacer) || isArray(replacer)) {
			Object.keys(replacer).forEach((prop) => {
				rawString = rawString.replaceAll('${' + prop + '}', replacer[prop]);
			});
		} else {
			rawString = rawString.replaceAll('${0}', replacer[prop]);
		}
	}

	return rawString;
};

/**
 * 初始化国际化插件
 * @param {I18nOptions} i18nOptions
 * @returns 带有install方法的vue插件对象
 */
const createI18n = (i18nOptions = {}) => {
	const lang = ref(i18nOptions.lang);
	const i18n = ref(noop);
	const config = i18nOptions.map || {};

	watch(
		lang,
		(val) => {
			const data = config[val];

			if (data) {
				i18n.value = function (tokens, replacer) {
					let sentence = data;
					tokens.split('.').every((key) => {
						sentence = sentence[key];
						return !sentence;
					});

					return sentence ? replace(sentence, replacer) : tokens;
				};
			} else {
				i18n.value = noop;
			}
		},
		{
			immediate: true,
		}
	);

	return {
		install(app) {
			Object.defineProperty(app.config.globalProperties, '$i18n', {
				get() {
					return i18n.value;
				},
			});
			Object.defineProperty(app.config.globalProperties, '$lang', {
				get() {
					return lang.value;
				},
				set(val) {
					lang.value = val;
				},
			});
		},
	};
};

export default createI18n;
